<template>
	<div class="app" v-cloak v-if="isOkShow === true">
		<div class="verify-container" :style="{ width: `${width}px` }">
			<div class="refresh" @click="reset">
				<svg t="1637315258145" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
					p-id="2420" width="20" height="20">
					<path
						d="M960 416V192l-73.056 73.056a447.712 447.712 0 0 0-373.6-201.088C265.92 63.968 65.312 264.544 65.312 512S265.92 960.032 513.344 960.032a448.064 448.064 0 0 0 415.232-279.488 38.368 38.368 0 1 0-71.136-28.896 371.36 371.36 0 0 1-344.096 231.584C308.32 883.232 142.112 717.024 142.112 512S308.32 140.768 513.344 140.768c132.448 0 251.936 70.08 318.016 179.84L736 416h224z"
						p-id="2421" fill="#8a8a8a"></path>
				</svg>
			</div>
			<div class="pic">
				<canvas class="canvas" ref="canvas" :width="width" :height="height" @click="createPointer"></canvas>
				<span class="pointer" v-for="(item, index) in pointer" :style="{ left: `${item.x}px`, top: `${item.y}px` }">
					<i>{{ index + 1 }}</i>
				</span>
			</div>
			<div :class="['toolbar', state]">
				<p v-if="state === 'fail'">验证失败</p>
				<p v-else-if="state === 'success'">验证通过</p>
				<p v-else>请顺序点击【<span v-for="(item, index) in tips" :key="index">{{ item.character }}</span>】</p>
			</div>
		</div>
	</div>
</template>

<script >
import { ElMessage } from "element-plus";
export default {
	props: {
		infos: Object
	},
	data() {
		return {
			bgImg: null,  // 背景图
			ctx: null, // 背景画笔
			fontArr: [], // 显示的字符
			tips: [], // 提示文字
			pointer: [], // 点击序号
			state: '', // success fail active
			timeIns: null,
			width: 320,
			height: 120,
			fontStr: '赵钱孙李周吴郑王朱秦尤许何吕施张孔曹严华金魏陶姜戚谢邹喻柏水窦章云苏潘葛奚范彭郎鲁韦昌马苗凤花方俞任袁柳酆鲍史唐',
			fontNum: 5,
			checkNum: 3,
			accuracy: 15,
			images: [
				'https://images.pexels.com/photos/2418973/pexels-photo-2418973.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1',
				'https://images.pexels.com/photos/5187070/pexels-photo-5187070.jpeg?auto=compress&cs=tinysrgb&w=600&lazy=load',
				'https://images.pexels.com/photos/3510717/pexels-photo-3510717.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1',
				'https://ts1.cn.mm.bing.net/th?id=OIP-C.7-6n_pwnAPz_IkgyRuRI2wHaEo&w=316&h=197&c=8&rs=1&qlt=90&o=6&dpr=1.4&pid=3.1&rm=2'
			],
			isOkShow: true
		}
	},
	mounted() {
		this.init()
	},

	beforeDestroy() {
		clearTimeout(this.timeIns)
	},
	methods: {
		init() {
			this.ctx = this.$refs['canvas'].getContext('2d');
            console.log(this.ctx);
			this.getImg();
		},
		getImg() {
			const img = document.createElement('img');
			const imagesLen = this.images.length;
			const randomIndex = Math.floor(Math.random() * imagesLen);
			img.crossOrigin = "Anonymous";
			img.src = this.images[randomIndex];
			this.bgImg = img;
			img.onload = () => {
				this.draw();
			}
		},
		draw() {
			// 绘制背景图
			this.ctx.drawImage(this.bgImg, 0, 0, this.width, this.height);
			for (let i = 0; i < this.fontNum; i++) {
				const character = this.getRandomCharacter();
				const fontSize = this.randomNum(20, this.height * 1 / 4);
				const fontWeight = Math.random() > 0.5 ? 'bold' : 'normal';
				const fontStyle = Math.random() > 0.5 ? 'italic' : 'normal';
				const fontFamily = Math.random() > 0.5 ? 'sans-serif' : 'serif'
				const x = this.width / this.fontNum * i + 10;
				const y = Math.random() * (this.height - fontSize);

				this.ctx.fillStyle = this.randomColor(0, 255);
				this.ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`;
				this.ctx.textBaseline = 'top';
				this.ctx.fillText(character, x, y);
				this.fontArr.push({
					character,
					// fontSize,
					x,
					y
				})
			}

			for (let i = 0; i < this.checkNum; i++) {
				const randomIndex = Math.floor(Math.random() * this.fontArr.length);
				const character = this.fontArr.splice([randomIndex], 1)[0];
				this.tips.push(character);
				// console.log(character, this.fontArr)
			}
		},
		// 获取随机字符
		getRandomCharacter() {
			const fontStrLen = this.fontStr.length;
			const randomIndex = Math.floor(Math.random() * fontStrLen);
			const character = this.fontStr.charAt([randomIndex]);

			// debugger
			const isSome = this.fontArr.some(item => {
				return item.character === character;
			})
			if (isSome) {
				console.log(`>>>${character}已存在>>>`)
				return this.getRandomCharacter();
			} else {
				return character;
			}
		},
		randomColor(min, max) {
			let r = this.randomNum(min, max)
			let g = this.randomNum(min, max)
			let b = this.randomNum(min, max)
			return 'rgb(' + r + ',' + g + ',' + b + ')'
		},
		randomNum(min, max) {
			return Math.floor(Math.random() * (max - min) + min)
		},
		createPointer(e) {
			const canvasRect = this.$refs.canvas.getBoundingClientRect();
			const x = e.offsetX - 20;
			const y = e.offsetY - 20;

			if (this.pointer.length < this.tips.length) {
				this.pointer.push({ x, y });
				// this.verify()
				this.state = 'active'
			}
			if (this.pointer.length === this.tips.length) {
				const isPass = this.verify();
				if (isPass) { // 验证成功
					this.state = 'success';
					this.isOkShow = false
					this.reset()
					sessionStorage.setItem('token', JSON.stringify(this.infos.token))
					sessionStorage.setItem('userInfo', JSON.stringify(this.infos.info))
					this.$router.push('/home')
					ElMessage({ type: "success", message: "登录成功" });
				} else {
					this.state = 'fail';
					// 如果失败则1000毫秒后重置
					this.timeIns = setTimeout(() => {
						this.reset()
					}, 1000)
				}
			}
		},

		// 判断精度
		verify() {
			const result = this.pointer.every((item, index) => {
				const _left = item.x > this.tips[index].x - this.accuracy;
				const _right = item.x < this.tips[index].x + this.accuracy;
				const _top = item.y > this.tips[index].y - this.accuracy;
				const _bottom = item.y < this.tips[index].y + this.accuracy;
				return _left && _right && _top && _bottom;
			})
			return result;
		},
		// 重置
		reset() {
			this.fontArr = [];
			this.tips = [];
			this.pointer = [];
			this.state = '';
			this.ctx.clearRect(0, 0, this.width, this.height);
			this.getImg();
		}
	}
}



</script>


<style scoped>
.app {
	z-index: 5;
	padding: 0;
	margin: 0;
	position: relative;
	top: 221px;
	right: 160px;
}

.verify-container {
	border: 1px solid #e4e4e4;
	margin: 20px auto;
	position: relative;
	overflow: hidden;
	user-select: none;
}

.pic {
	position: relative;
}

.canvas {
	display: block;
}

.pointer {
	background: #1abd6c;
	border-radius: 50%;
	padding: 15px;
	position: absolute;
}

.pointer i {
	color: #fff;
	font-style: normal;
	font-size: 12px;
	display: flex;
	justify-content: center;
	align-items: center;
	position: absolute;
	left: 0;
	top: 0;
	right: 0;
	bottom: 0;
}

.toolbar {
	width: 100%;
	height: 40px;
	border: 1px solid #e4e4e4;
	background: #f7f7f7;
	color: #666;
	font-size: 14px;
	display: flex;
	justify-content: center;
	align-items: center;
	position: relative;
}

.toolbar.active {
	color: #fff;
	background: #1991FA;
	border: 1px solid #1991FA;
}

.toolbar.success {
	color: #fff;
	background: #52CCBA;
	border: 1px solid #52CCBA;
}

.toolbar.fail {
	color: #fff;
	background: #f57a7a;
	border: 1px solid #f57a7a;
}

.refresh {
	display: flex;
	position: absolute;
	right: 10px;
	top: 10px;
	z-index: 2;
	cursor: pointer;
}
</style>
